package co.edu.uniandes.autoadaptacion.mbroker.checker;

import java.util.ArrayList;
import java.util.List;

import co.edu.uniandes.autoadaptacion.mbroker.checker.rule.IRule;
import co.edu.uniandes.autoadaptacion.mbroker.checker.rule.RuleA;
import co.edu.uniandes.autoadaptacion.mbroker.checker.scenario.IScenario;
import co.edu.uniandes.autoadaptacion.mbroker.checker.scenario.ScenarioDos;
import co.edu.uniandes.autoadaptacion.mbroker.checker.scenario.ScenarioUno;
import co.edu.uniandes.autoadaptacion.mbroker.matrix.Matrix;


public class Checker{
	
	private static Checker instance;
	private boolean threadStarted;
	private List<IScenario> scenarios;
	private List<IRule> rulesList;
	private RulesThread rt;

	private Checker() {
		System.out.println("Checker instance created. This is made just one time.");
		// Checker debe manejar la lista de todos los escenarios configurados
		// para el par consumidor-proveedor.
		// La regla solo mantiene el listado de los escenarios definidos para ella.
		scenarios = new ArrayList<IScenario>();
		scenarios.add(ScenarioUno.getInstance());
		scenarios.add(ScenarioDos.getInstance());
		
		rulesList = new ArrayList<IRule>();
		rulesList.add(RuleA.getInstance());	
	}

	public static Checker getInstance() {
		if (instance == null) {
			synchronized (Checker.class) { // 1
				if (instance == null) // 2
					instance = new Checker(); // 3
			}
		}
		return instance;
	}
	
	public void checkRules() {
		System.out.println("Checker::checkRules");
		if(!threadStarted){
			System.out.println("Checker::checkRules::Start thread");
			threadStarted = true;
			rt = new RulesThread();
			new Thread(rt).start();
		}else
			System.out.println("Checker::checkRules::Thread already started");

	}

	/**
	 * Recorre todas las reglas, obtiene los que cumplan y luego selecciona uno.
	 * @return
	 */
	public String getNewService() {
		System.out.println("Checker::getNewService");
		Matrix im = Matrix.getInstance();
		
		// 1. Obtengo el listado de servicios que cumplen para cada regla
		System.out.println("RulesThread::Some fail - Getting all services");
		int[] contadorCumplidores = new int[im.getServiceMatrixLenght()];
		for(IRule rule : rulesList){
			rule.returnAccomplishServices(contadorCumplidores);						
		}
		
		// Asignando el nuevo servicio por defecto
		(new Selector(im)).selectService(contadorCumplidores, rulesList.size(), im.getDefaultServiceIndex());
		
		return im.getDefaultService();
	}
	
	public void updateScenario(String scenarioName, double value){
//		System.out.println("Checker::updateScenario");
		boolean success = false;
				 
		for(IScenario i : scenarios){
			String className = i.getClass().getSimpleName();
//			System.out.println("Checker::updateScenario::className = "+className);
//			System.out.println("Checker::updateScenario::scenarioName = "+scenarioName+" - newValue = "+value);
			if(className.equals(scenarioName)){
				success = i.setNewScenarioValue(value);
				System.out.println("Checker::updateScenario::Change Scenario - newValue = "+value+" "+success);
			}
		}
//		System.out.println("Checker::updateScenario::success = "+success);
	}

}
